#pragma once

#include <string>
#include <vector>
#include <queue>
#include <memory>
#include <vector>
#include <atomic>
#include <string>
#include <sstream>
#include <chrono>
#include <ThostFtdcTraderApi.h>
#include <ThostFtdcMdApi.h>
#include <boost/serialization/vector.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <XUtil/XStr.hpp>
#include <XUtil/XXml.hpp>
#include <XUtil/XState.hpp>
#include <XUtil/XDateTime.hpp>
#include <boost/circular_buffer.hpp>

#include <zqdb.h>
#include <zqdbmodule.h>
#include <zqctp.h>

#include <future>
#include <mdb.pb.h>
#include <zqdbase.pb.h>
#include <zqdb.pb.h>

#include <mdbdf.hpp>
#include <limits>
#include <locale>
#include <codecvt>
#include <XUtil/XDateTime.hpp>
#include <zqstr.hpp>

#define STR_MODULE_NAME STR_CTP_MODULE

extern HZQDB g_ctp_module;
extern tagModuleInfoEx* g_module_info;
#define all_exchange_count 6
extern const char* all_exchange[all_exchange_count];

extern const size_t MaxProductCountPerExchange;
extern const size_t MaxCodeCountPerProduct;

//#define USE_LOGXXX

#ifdef USE_LOGXXX

class LogMgr
{
private:
	std::shared_ptr<std::thread> thread_;
	std::mutex mutex_;
	std::condition_variable cv_;
	std::queue<std::string> records_;
	void DoFlush();
	LogMgr();
	~LogMgr();
	void DoLogOut(std::string&& str);
public:
	static void Init();
	static void Term();
	static void LogOut(const char *fmt, ...);
};
#define LOGXXX_INIT() LogMgr::Init()
#define LOGXXX_TERM() LogMgr::Term()
#define LOGXXX(format, ...) \
    do { \
        char t[64] = { 0 }; time_t tt; time(&tt); \
		strftime(t, 64, "%Y-%m-%d %H:%M:%S", localtime(&tt)); \
        LogMgr::LogOut("%s " format "\n", t,  ##__VA_ARGS__); \
    } while(0)

#else

#define LOGXXX_INIT() 
#define LOGXXX_TERM()
#define LOGXXX(format, ...) 

#endif//USE_LOGXXX

#include <algorithm>
#include <boost/circular_buffer.hpp>
#include <XUtil/XServer.hpp>
#include <XUtil/XStr.hpp>
#include <XUtil/XState.hpp>
#include <XUtil/XDateTime.hpp>

#ifndef LOG4E
#define LOG4E(format,...) printf("%s " format "\n", __FUNCTION__, ##__VA_ARGS__)
#endif//LOG4E
#ifndef LOG4W
#define LOG4W LOG4E
#endif//LOG4W
#ifndef LOG4I
#define LOG4I LOG4E
#endif//LOG4I
#ifndef LOG4D
#define LOG4D LOG4E
#endif//LOG4D

template<typename Ty>
static inline bool IsZeroValue(Ty v) { return ZQDBIsZeroValue(v); }
template<typename Ty>
static inline bool IsInvalidValue(Ty v) { return ZQDBIsInvalidValue(v); }
template<typename Ty>
static inline bool IsEqualValue(Ty x, Ty y) { return ZQDBIsEqualValue(x, y); }

#define RECORD_TYPE_UpdateMarketData 0
#define RECORD_TYPE_BeginNewTradingDay 1
#define RECORD_TYPE_InitNewTradingDay 2
#define RECORD_TYPE_EndNewTradingDay 3

// utf8转gbk
std::string utf8_to_gbk(const std::string &str);
// gbk转utf8
std::string gbk_to_utf8(const std::string &str);

//////////////////////////////////////////////////////////////////////////
//请求格式：{ "RequestApi":"Api", "RequestID": 0, "Data": { Property:Value } }
//返回格式：{ "ReturnApi":"Api", "ErrorMsg": "成功", "ErrorID": 0, "RequestID": 0, "IsLast": 0, "Data": { Property:Value } }
//其中:
//Property对应CTP数据结构数据，Value对应CTP数据结构数据值
//请求数据里必须有 RequestApi:Api 属性，例如：{ RequestApi:ReqOrderInsert }
//返回数据里必填ReturnApi:Api，例如：{ ReturnApi:RtnOrder }
//ErrorMsg：返回消息内容
//ErrorID：返回错误值，0表示成功，其他表示错误
//RequestID：请求传入的RequestID原样返回
//IsLast：标示是否是最后一个包
//Data：数据内容，是Property:Value组成的对象
//请求出错：
//请求异常服务器直接断开和客户端连接
//请求非异常错误服务器返回ReturnApi=RequestApi
//返回出错：
//返回异常服务器直接断开和客户端连接
//返回非异常错误ReturnApi=CTP返回相关Api
//////////////////////////////////////////////////////////////////////////
//BrokerID统一为：9999
//标准CTP：
//第一组：Trade Front：180.168.146.187:10000，Market Front：180.168.146.187 : 10010；【电信】
//第二组：Trade Front：180.168.146.187 : 10001，Market Front：180.168.146.187 : 10011；【电信】
//第三组：Trade Front：218.202.237.33 : 10002，Market Front：218.202.237.33 : 10012；【移动】
//账号115569 密码 654321
//WEB
//IP:123.57.8.45:5588
//帐号： administrator
//密码 : af(201 - 30326 * &jUYjes)yy
//////////////////////////////////////////////////////////////////////////

typedef char TThostFtdcUriAddressType[2048];

class CTPUserLoginInfo : public CThostFtdcReqUserLoginField
{
public:
	CTPUserLoginInfo()
	{
		memset((CThostFtdcReqUserLoginField*)this, 0, sizeof(CThostFtdcReqUserLoginField));
		//FrontAddress;
		//NsAddress;
		LoginMode = 0;
		memset(&ProductInfo, 0, sizeof(ProductInfo));
		memset(&AuthCode, 0, sizeof(AuthCode));
		memset(&AppID, 0, sizeof(AppID));
		//MdFrontAddress;
		//MdNsAddress;
	}

	CTPUserLoginInfo(const CTPUserLoginInfo& userinfo)
	{
		memcpy((CThostFtdcReqUserLoginField*)this, (CThostFtdcReqUserLoginField*)&userinfo, sizeof(CThostFtdcReqUserLoginField));
		FrontAddress = userinfo.FrontAddress;
		NsAddress = userinfo.NsAddress;
		LoginMode = userinfo.LoginMode;
		memcpy(ProductInfo, userinfo.ProductInfo, sizeof(ProductInfo));
		memcpy(AuthCode, userinfo.AuthCode, sizeof(AuthCode));
		memcpy(AppID, userinfo.AppID, sizeof(AppID));
		MdFrontAddress = userinfo.MdFrontAddress;
		MdNsAddress = userinfo.MdNsAddress;
	}

	///前置机服务器网络地址
	//TThostFtdcUriAddressType FrontAddress;
	std::vector<std::string> FrontAddress;
	///名字服务器网络地址
	//TThostFtdcUriAddressType NsAddress;
	std::vector<std::string> NsAddress;
	///登录模式
	TThostFtdcLoginModeType	LoginMode;
	///用户端产品信息
	TThostFtdcProductInfoType ProductInfo; 
	///认证码
	TThostFtdcAuthCodeType	AuthCode;
	///App代码
	TThostFtdcAppIDType	AppID;
	///行情前置机服务器网络地址
	//TThostFtdcUriAddressType MdFrontAddress;
	std::vector<std::string> MdFrontAddress;
	///行情名字服务器网络地址
	//TThostFtdcUriAddressType MdNsAddress;
	std::vector<std::string> MdNsAddress;
};

bool parseUserInfoFromString(CTPUserLoginInfo& userInfo, const std::string& jsonString);

bool parse_userinfo(CTPUserLoginInfo& userinfo, const boost::property_tree::ptree& cfg, bool market = false);

//////////////////////////////////////////////////////////////////////////

#define DefaultDecimal		(3)		//默认小数位数
#define AmountDecimal		(2)		//额小数位数
#define AmountRatioDecimal	(2)		//额比例位数
#define VolumeDecimal		(0)		//量小数位数

unsigned long CTPDate2Date(const TThostFtdcDateType& Date);
unsigned long CTPTime2Time(const TThostFtdcTimeType& Time);

#define CHECKDATETIME(d,t)

inline TThostFtdcPosiDirectionType CTPDirection2PosiDirection(TThostFtdcDirectionType direction) {
	switch (direction)
	{
	case THOST_FTDC_D_Buy:
		return THOST_FTDC_PD_Long;
	case THOST_FTDC_D_Sell:
		return THOST_FTDC_PD_Short;
	}
	return THOST_FTDC_PD_Net;
}

//////////////////////////////////////////////////////////////////////////

//-1，表示网络连接失败；
//-2，表示未处理请求超过许可数；
//-3，表示每秒发送请求数超过许可数。

///CTPTrade内部使用的发送请求宏
#define DoRequest(func,req,reqId) \
	do \
	{ \
		rlt = func(&req, reqId); \
		if (rlt==-2 || rlt==-3) \
		{ \
			std::this_thread::yield(); \
		} \
		else \
		{ \
			break; \
		} \
	} while(true)

// 是否收到成功的响应
bool IsErrorRspInfo(const CThostFtdcRspInfoField *pRspInfo);

//////////////////////////////////////////////////////////////////////////

enum
{
	CTP_STAT_DISCONNECT					= 0,
	CTP_STAT_CONNECTING					= 1,
	CTP_STAT_CONNECT					= 2,
	CTP_STAT_AUTHENTICATE				= 3,
	CTP_STAT_LOGIN						= 4,
	CTP_STAT_INVESTORINFO				= 5,
	CTP_STAT_TRADINGACCOUNT				= 6,
	CTP_STAT_TRADINGCODE				= 7,
	CTP_STAT_NOTICE						= 8,
	CTP_STAT_CFMMC						= 9,
	CTP_STAT_QRYSETTLEMENTINFOCONFIRM	= 10,
	CTP_STAT_QRYSETTLEMENTINFO			= 11,
	CTP_STAT_SETTLEMENTINFOCONFIRM		= 12,
	CTP_STAT_ACCOUNTREGISTER			= 13,
	CTP_STAT_BANK						= 14,
	CTP_STAT_EXCHANGE					= 15,
	CTP_STAT_PRODUCT					= 16,
	CTP_STAT_INSTRUMENT					= 17,
	CTP_STAT_DEPTHMARKETDATA			= 18,
	CTP_STAT_INSTRUMENTSTATUS			= 19,
	CTP_STAT_COMMISSIONRATE				= 20,
	CTP_STAT_PARKEDORDER				= 21,
	CTP_STAT_ORDER						= 22,
	CTP_STAT_TRADE						= 23,
	CTP_STAT_POSITION					= 24,
	CTP_STAT_POSITIONDETAIL				= 25,
	CTP_STAT_MAX,
};

struct CTPExchangeInfoEx;
struct CTPProductInfoEx;
struct CTPCommodityInfoEx;
struct ExchangeInfo;
struct ProductInfo;
struct CommodityInfo;

struct CTPExchangeInfoEx : public CThostFtdcExchangeField, public CThostFtdcInstrumentStatusField
{
	const char* Exchange;
	const char* Name;

	CTPExchangeInfoEx() {
		CThostFtdcExchangeField* p = this;
		memset((CThostFtdcExchangeField*)this, 0, sizeof(CThostFtdcExchangeField));
		memset((CThostFtdcInstrumentStatusField*)this, 0, sizeof(CThostFtdcInstrumentStatusField));
		Exchange = p->ExchangeID;
		Name = p->ExchangeName;
	}
	CTPExchangeInfoEx(const CThostFtdcExchangeField& o) {
		CThostFtdcExchangeField* p = this;
		memcpy((CThostFtdcExchangeField*)this, &o, sizeof(CThostFtdcExchangeField));
		memset((CThostFtdcInstrumentStatusField*)this, 0, sizeof(CThostFtdcInstrumentStatusField));
		Exchange = p->ExchangeID;
		Name = p->ExchangeName;
	}
};
struct CTPProductInfoEx : public CThostFtdcProductField, public CThostFtdcInstrumentStatusField, public CThostFtdcInstrumentCommissionRateField
{
	const char* Exchange;
	const char* Product;
	const char* Name;
	//size_t count = 0;
	std::shared_ptr<CTPExchangeInfoEx> exchange_;
	std::shared_ptr<CTPCommodityInfoEx> main_commodity_;
	std::shared_ptr<CTPCommodityInfoEx> second_commodity_;
	CTPProductInfoEx() {
		CThostFtdcProductField* p = this;
		memset((CThostFtdcProductField*)this, 0, sizeof(CThostFtdcProductField));
		memset((CThostFtdcInstrumentStatusField*)this, 0, sizeof(CThostFtdcInstrumentStatusField));
		memset((CThostFtdcInstrumentCommissionRateField*)this, 0, sizeof(CThostFtdcInstrumentCommissionRateField));
		Exchange = p->ExchangeID;
		Product = p->ProductID;
		Name = p->ProductName;
	}
	CTPProductInfoEx(const CThostFtdcProductField& o) {
		CThostFtdcProductField* p = this;
		memcpy((CThostFtdcProductField*)this, &o, sizeof(CThostFtdcProductField));
		memset((CThostFtdcInstrumentStatusField*)this, 0, sizeof(CThostFtdcInstrumentStatusField));
		memset((CThostFtdcInstrumentCommissionRateField*)this, 0, sizeof(CThostFtdcInstrumentCommissionRateField));
		Exchange = p->ExchangeID;
		Product = p->ProductID;
		Name = p->ProductName;
	}
};
struct CTPCommodityInfoEx : public CThostFtdcInstrumentField, public CThostFtdcInstrumentStatusField
	, public CThostFtdcDepthMarketDataField
{
	const char* Exchange;
	const char* Product;
	const char* Code;
	const char* Name;
	size_t pos = 0;
	std::shared_ptr<CTPProductInfoEx> product_; //品种

	CTPCommodityInfoEx() {
		CThostFtdcInstrumentField* p = this;
		memset((CThostFtdcInstrumentField*)this, 0, sizeof(CThostFtdcInstrumentField));
		memset((CThostFtdcDepthMarketDataField*)this, 0, sizeof(CThostFtdcDepthMarketDataField));
		memset((CThostFtdcInstrumentStatusField*)this, 0, sizeof(CThostFtdcInstrumentStatusField));
		Exchange = p->ExchangeID;
		Product = p->ProductID;
		Code = p->InstrumentID;
		Name = p->InstrumentName;
	}
	CTPCommodityInfoEx(const CThostFtdcInstrumentField& o) {
		CThostFtdcInstrumentField* p = this;
		memcpy((CThostFtdcInstrumentField*)this, &o, sizeof(CThostFtdcInstrumentField));
		memset((CThostFtdcDepthMarketDataField*)this, 0, sizeof(CThostFtdcDepthMarketDataField));
		memset((CThostFtdcInstrumentStatusField*)this, 0, sizeof(CThostFtdcInstrumentStatusField));
		Exchange = p->ExchangeID;
		Product = p->ProductID;
		Code = p->InstrumentID;
		Name = p->InstrumentName;
	}
};

struct ExchangeInfo : public tagExchangeInfo
{
	std::shared_ptr<CTPExchangeInfoEx> sp;
	HZQDB h = nullptr;

	ExchangeInfo()
	{
		tagExchangeInfo* p = this;
		memset(p, 0, sizeof(tagExchangeInfo));
	}
};
struct ProductInfo : public tagProductInfo
{
	std::shared_ptr<CTPProductInfoEx> sp;
	std::shared_ptr<ExchangeInfo> parent;
	HZQDB h = nullptr;

	ProductInfo()
	{
		tagProductInfo* p = this;
		memset(p, 0, sizeof(tagProductInfo));
	}
};
struct CodeInfo : public tagCTPCodeInfo
{
	std::shared_ptr<CTPCommodityInfoEx> sp;
	std::shared_ptr<ProductInfo> parent;
	HZQDB h = nullptr;
	//CTPKDATA kdata[CYC_MAX] = { 0 };

	CodeInfo()
	{
		tagCTPCodeInfo* p = this;
		memset(p, 0, sizeof(tagCTPCodeInfo));
		this->PriceTick = 0.01; //最小变动价位
		this->YClose = ZQDB_INVALID_VALUE; //昨收
		this->YSettle = ZQDB_INVALID_VALUE; //昨结
		this->Settle = ZQDB_INVALID_VALUE; //结算价
		this->Upper = ZQDB_INVALID_VALUE; //涨停板价
		this->Lower = ZQDB_INVALID_VALUE; //跌停板价
		this->Open = ZQDB_INVALID_VALUE;
		this->High = ZQDB_INVALID_VALUE;
		this->Low = ZQDB_INVALID_VALUE;
		this->Close = ZQDB_INVALID_VALUE; // 交易价格，当然也是最新价，单位：元
		this->Amount = 0; // 总额
		this->Volume = 0; // 总成交量，单位：最小单位(股，张等)
		this->Bid1 = ZQDB_INVALID_VALUE; //申买价
		this->Bid2 = ZQDB_INVALID_VALUE; //申买价
		this->Bid3 = ZQDB_INVALID_VALUE; //申买价
		this->Bid4 = ZQDB_INVALID_VALUE; //申买价
		this->Bid5 = ZQDB_INVALID_VALUE; //申买价
		this->BidV1 = 0; //申买量
		this->BidV2 = 0; //申买量
		this->BidV3 = 0; //申买量
		this->BidV4 = 0; //申买量
		this->BidV5 = 0; //申买量
		this->Ask1 = ZQDB_INVALID_VALUE; //申卖价
		this->Ask2 = ZQDB_INVALID_VALUE; //申卖价
		this->Ask3 = ZQDB_INVALID_VALUE; //申卖价
		this->Ask4 = ZQDB_INVALID_VALUE; //申卖价
		this->Ask5 = ZQDB_INVALID_VALUE; //申卖价
		this->AskV1 = 0; //申卖量
		this->AskV2 = 0; //申卖量
		this->AskV3 = 0; //申卖量
		this->AskV4 = 0; //申卖量
		this->AskV5 = 0; //申卖量

		///昨持仓量
		//this->PreOpenInterest = ZQDB_INVALID_VALUE;
		///持仓量
		//double OpenInterest = ZQDB_INVALID_VALUE;

		///昨虚实度
		//double	PreDelta = ZQDB_INVALID_VALUE;
		///今虚实度
		//double	CurrDelta = ZQDB_INVALID_VALUE;
		///当日均价
		//double	AveragePrice = ZQDB_INVALID_VALUE;

		///交割年份
		//uint32_t	DeliveryYear = 0;
		///交割月
		//uint32_t	DeliveryMonth = 0;
		///市价单最大下单量
		//double	MaxMarketOrderVolume = ZQDB_INVALID_VALUE;
		///市价单最小下单量
		//double	MinMarketOrderVolume = ZQDB_INVALID_VALUE;
		///限价单最大下单量
		//double	MaxLimitOrderVolume = ZQDB_INVALID_VALUE;
		///限价单最小下单量
		//double	MinLimitOrderVolume = ZQDB_INVALID_VALUE;
		///合约数量乘数
		//uint32_t	VolumeMultiple 1;
		///创建日
		//uint32_t	CreateDate = 0;
		///上市日
		//uint32_t	OpenDate = 0;
		///到期日
		//uint32_t	ExpireDate = 0;
		///开始交割日
		//uint32_t	StartDelivDate = 0;
		///结束交割日
		//uint32_t	EndDelivDate = 0;
		///合约生命周期状态
		//char	InstLifePhase = 0;
		///当前是否交易
		//byte	IsTrading = 0;
		///持仓类型
		//char	PositionType = 0;
		///持仓日期类型
		//char	PositionDateType = 0;
		///多头保证金率
		//double	LongMarginRatio = ZQDB_INVALID_VALUE;
		///空头保证金率
		//double	ShortMarginRatio = ZQDB_INVALID_VALUE;
		///是否使用大额单边保证金算法
		//char	MaxMarginSideAlgorithm = 0;
		///基础商品代码
		//char	UnderlyingInstrID[31];
		///执行价
		this->StrikePrice = ZQDB_INVALID_VALUE;
		///期权类型
		//char	OptionsType;
		///合约基础商品乘数
		//double	UnderlyingMultiple = 1;
		///组合类型
		//char	CombinationType;
	}
};

///

struct CTPAccountInfo : public CThostFtdcTradingAccountField
{
	const char* id;
	//静态权益=上日结算-出金金额+入金金额 -> account.PreBalance - account.Withdraw + account.Deposit
	//动态权益=静态权益+ 平仓盈亏+ 持仓盈亏- 手续费 -> 静态权益+ account.CloseProfit + account.PositionProfit - account.Commission
	//可用资金(动态权益-占用保证金- 冻结保证金- 冻结手续费- 交割保证金) -> account.Available
	//风险度=当前保证金总额/期货结算准备金
	double Static = 0.;
	double Dynamic = 0.;
	//double Available = 0.;
	double Risk = 0.;
	CTPAccountInfo() {
		CThostFtdcTradingAccountField* p = this;
		memset((CThostFtdcTradingAccountField*)this, 0, sizeof(CThostFtdcTradingAccountField));
		id = p->AccountID;
	}
	CTPAccountInfo(const CThostFtdcTradingAccountField& o) {
		CThostFtdcTradingAccountField* p = this;
		memcpy((CThostFtdcTradingAccountField*)this, &o, sizeof(CThostFtdcTradingAccountField));
		id = p->AccountID;
		Static = PreBalance - Withdraw + Deposit;
		Dynamic = CloseProfit + PositionProfit - Commission;
		//Available;
		Risk = CurrMargin / Balance;
	}
};
struct CTPOrderInfo : public CThostFtdcOrderField
{
	const char* id = nullptr;
	//size_t time_ = 0;
	CTPOrderInfo() {
		CThostFtdcOrderField* p = this;
		memset((CThostFtdcOrderField*)this, 0, sizeof(CThostFtdcOrderField));
		id = p->OrderSysID;
	}
	CTPOrderInfo(const CThostFtdcOrderField& o) {
		CThostFtdcOrderField* p = this;
		memcpy((CThostFtdcOrderField*)this, &o, sizeof(CThostFtdcOrderField));
		id = p->OrderSysID;
		/*time_ = CTPTime2Time(p->UpdateTime);
		if (time_ == 0)
			time_ = CTPTime2Time(p->InsertTime);*/
	}

	inline bool is_valid() {
		return !is_rejected() && !is_cancelled() && !is_all_traded();
	}

	inline bool is_buy() {
		return this->Direction == THOST_FTDC_D_Buy;
	}

	inline bool is_sell() {
		return this->Direction == THOST_FTDC_D_Sell;
	}

	inline bool is_open() {
		return this->CombOffsetFlag[0] == THOST_FTDC_OF_Open;
	}

	inline bool is_close_today() {
		return this->CombOffsetFlag[0] == THOST_FTDC_OF_CloseToday;
	}

	inline bool is_rejected() {
		switch (this->OrderSubmitStatus)
		{
			///已经提交
		case THOST_FTDC_OSS_InsertSubmitted:
			///撤单已经提交
		case THOST_FTDC_OSS_CancelSubmitted:
			///修改已经提交
		case THOST_FTDC_OSS_ModifySubmitted:
			///已经接受
		case THOST_FTDC_OSS_Accepted:
			return false;
			///报单已经被拒绝
		case THOST_FTDC_OSS_InsertRejected:
			///撤单已经被拒绝
		case THOST_FTDC_OSS_CancelRejected:
			///改单已经被拒绝
		case THOST_FTDC_OSS_ModifyRejected:
			return true;
		}
		return false;
	}

	/*inline bool is_submitted() {
	switch (this->OrderStatus)
	{
	///全部成交
	#define THOST_FTDC_OST_AllTraded '0'
	///部分成交还在队列中
	#define THOST_FTDC_OST_PartTradedQueueing '1'
	///部分成交不在队列中
	#define THOST_FTDC_OST_PartTradedNotQueueing '2'
	///未成交还在队列中
	#define THOST_FTDC_OST_NoTradeQueueing '3'
	///未成交不在队列中
	#define THOST_FTDC_OST_NoTradeNotQueueing '4'
	///撤单
	#define THOST_FTDC_OST_Canceled '5'
	///未知
	#define THOST_FTDC_OST_Unknown 'a'
	///尚未触发
	#define THOST_FTDC_OST_NotTouched 'b'
	///已触发
	#define THOST_FTDC_OST_Touched 'c'
	}
	}*/

	inline bool is_cancelled() {
		return this->OrderStatus == THOST_FTDC_OST_Canceled;
	}

	inline bool is_all_traded() {
		return this->VolumeTraded >= this->VolumeTotalOriginal;
	}
};
struct CTPTradeInfo : public CThostFtdcTradeField
{
	const char* id = nullptr;
	CTPTradeInfo() {
		CThostFtdcTradeField* p = this;
		memset((CThostFtdcTradeField*)this, 0, sizeof(CThostFtdcTradeField));
		id = p->TradeID;
	}
	CTPTradeInfo(const CThostFtdcTradeField& o) {
		CThostFtdcTradeField* p = this;
		memcpy((CThostFtdcTradeField*)this, &o, sizeof(CThostFtdcTradeField));
		id = p->TradeID;
	}

	inline bool is_buy() {
		return this->Direction == THOST_FTDC_D_Buy;
	}

	inline bool is_sell() {
		return this->Direction == THOST_FTDC_D_Sell;
	}

	inline bool is_open() {
		return this->OffsetFlag == THOST_FTDC_OF_Open;
	}

	inline bool is_close_today() {
		return this->OffsetFlag == THOST_FTDC_OF_CloseToday;
	}

};
struct CTPPositionInfo : public CThostFtdcInvestorPositionField
{
	const char* id = nullptr;
	CTPPositionInfo() {
		CThostFtdcInvestorPositionField* p = this;
		memset((CThostFtdcInvestorPositionField*)this, 0, sizeof(CThostFtdcInvestorPositionField));
		id = p->InstrumentID;
	}
	CTPPositionInfo(const CThostFtdcInvestorPositionField& o) {
		CThostFtdcInvestorPositionField* p = this;
		memcpy((CThostFtdcInvestorPositionField*)this, &o, sizeof(CThostFtdcInvestorPositionField));
		id = p->InstrumentID;
	}

	inline bool is_valid() {
		return volume() > 0;
	}

	inline bool is_short() {
		return this->PosiDirection == THOST_FTDC_PD_Short;
	}

	inline int yd_volume() {
		return this->YdPosition;
	}

	inline int today_volume() {
		return this->TodayPosition;
	}

	inline int volume() { //当前持仓
		return this->Position;
	}

	inline int frozen() { //冻结保证金
		if (this->PosiDirection == THOST_FTDC_PD_Short) {
			return this->LongFrozen;
		}
		else {
			return this->ShortFrozen;
		}
	}

	inline int available() {
		return volume() - frozen();
	}

	inline double cost() {
		return this->PositionCost; //当前持仓成本（不包含佣金）
	}

	inline double commission() { //总的佣金费用
		return this->Commission;
	}

	inline double profit() { //当前持仓盈亏
		return this->PositionProfit;
	}

	inline double close_profit() { //已经平仓的盈亏
		return this->CloseProfit;
	}
};

//比较更新判断，判断是更新旧周期还是新增周期
bool SameCycle(HZQDB h, uint32_t olddate, uint32_t newdate, uint32_t oldtime, uint32_t newtime, PERIODTYPE cycle, size_t cycleex);

class CTPGlobal
{
public:
	CTPGlobal();
};
